package com.woniuxy.core.service.impl;

import com.alipay.api.response.AlipayTradeQueryResponse;
import com.woniuxy.config.PayUtil;
import com.woniuxy.core.mapper.PaymentMapper;
import com.woniuxy.core.service.PaymentService;
import com.woniuxy.entity.AllUser;
import com.woniuxy.entity.PaymentRecord;
import com.woniuxy.entity.PaymentStatus;
import com.woniuxy.entity.ShopOrder;
import com.woniuxy.entity.VO.RenkingVO;
import com.woniuxy.enums.order.ShopOrderStatus;
import com.woniuxy.feign.ContentApi;
import com.woniuxy.feign.OrderApi;
import com.woniuxy.feign.UserApi;
import com.woniuxy.mq.message.PaymentSuccessMessage;
import com.woniuxy.util.ResponseData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author hq
 * @Date 2025/7/14$ 17:32$
 * @Description 支付服务实现
 **/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private PaymentMapper paymentMapper;

    @Autowired
    private OrderApi orderApi;

    @Autowired
    private UserApi userApi;

    @Autowired
    private ContentApi contentApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private PayUtil payUtil;

    // 分布式锁前缀
    private static final String LOCK_PREFIX = "payment:lock:";

    // 锁过期时间（30秒，防止死锁）
    private static final long LOCK_EXPIRE_SECONDS = 30;

    // 支付成功交换机和路由键
    private static final String ORDER_PAY_SUCCESS_EXCHANGE = "order.pay.success.exchange";
    private static final String ORDER_PAY_SUCCESS_ROUTING_KEY = "order.pay.success";

    /**
     * 创建支付订单
     */
    @Override
    public ResponseData createPaymentOrder(PaymentRecord paymentRecord) {
        // 1. 验证订单信息
        ShopOrder order = paymentMapper.getOrderInfo(paymentRecord.getOrderId());
        log.info("order:{}", order);
        if (order == null || !order.getStatus().equals(ShopOrderStatus.PENDING.getCode())) {
            throw new RuntimeException("订单不存在或已支付");
        }
        //判断是否是跑腿订单
        if (order.getOrderNumber() !=null && order.getOrderNumber().startsWith("ORD")){
            RenkingVO renkingVO = new RenkingVO(order.getSellerId(),order.getTotalAmount());
            System.out.println("paymentRecord"+order);
            orderApi.updateRanking(order.getSellerId(),order.getTotalAmount());
            System.out.println("order"+order);
            orderApi.updatePay(order.getRunNumber());
        }

        // 2. 生成支付记录
        paymentRecord.setTransactionId(generateTransactionId());
        paymentRecord.setStatus(PaymentStatus.PENDING.getCode());
        paymentRecord.setCreateTime(new Date());
        paymentRecord.setUpdateTime(new Date());
        paymentRecord.setOrderNumber(order.getOrderNumber());
        paymentRecord.setAmount(order.getTotalAmount());
        paymentRecord.setPaymentMethod(paymentRecord.getPaymentMethod());
        paymentMapper.insert(paymentRecord);
        // 3. 根据支付方式处理
        Map<String, String> paymentParams = null;
        processWalletPayment(order, paymentRecord);
        paymentParams = new HashMap<>(); // 钱包支付无需前端跳转第三方
        return ResponseData.ok(paymentParams);
    }

    /**
     * 处理钱包支付
     */
    private void processWalletPayment(ShopOrder order, PaymentRecord paymentRecord) {
        // 1. 校验用户钱包余额
        AllUser user = userApi.getUserInfoAPI(Long.valueOf(order.getUserId()));
        if (user.getBalance().compareTo(paymentRecord.getAmount()) < 0) {
            throw new RuntimeException("钱包余额不足");
        }

        // 2. 扣减余额（使用分布式锁保证原子性）
        String lockKey = LOCK_PREFIX + "wallet:" + order.getUserId();
        String lockValue = UUID.randomUUID().toString();

        try {
            Boolean locked = redisTemplate.opsForValue().setIfAbsent(
                    lockKey,
                    lockValue,
                    LOCK_EXPIRE_SECONDS,
                    TimeUnit.SECONDS
            );

            if (!locked) {
                throw new RuntimeException("系统繁忙，请稍后再试");
            }

            // 重新验证余额（防止并发问题）
            user = userApi.getUserInfoAPI(Long.valueOf(order.getUserId()));
            if (user.getBalance().compareTo(paymentRecord.getAmount()) < 0) {
                throw new RuntimeException("钱包余额不足");
            }

            // 扣减余额
            userApi.deductBalance(Long.valueOf(order.getUserId()), paymentRecord.getAmount());
            log.info("用户{}余额扣减成功，余额为{}", order.getUserId(), user.getBalance());
            // 3. 增加商家余额
            userApi.increaseBalance(Long.valueOf(order.getSellerId()), paymentRecord.getAmount());
            log.info("用户{}余额增加成功，余额为{}", order.getSellerId(), user.getBalance());

            // 4. 更新支付记录状态
            paymentRecord.setStatus(PaymentStatus.SUCCESS.getCode());
            paymentRecord.setUpdateTime(new Date());
            paymentMapper.updateById(paymentRecord);

            // 5. 更新订单状态
            order.setStatus(ShopOrderStatus.PAID.getCode());
            log.info("订单{}状态更新成功：{} -> {}", order.getId(), order.getStatus(), ShopOrderStatus.PAID.getCode());
            order.setUpdateTime(new Date());
            orderApi.updateOrderStatus(order.getId(), order.getStatus());
            log.info("订单{}更新成功", order.getStatus());
            contentApi.updateStatus(order.getItemId(), 2);
            log.info("内容更新成功", order.getItemId());

            // 6. 发送支付成功消息
            sendPaymentSuccessMessage(order, paymentRecord);

        } finally {
            // 释放锁
            releaseLock(lockKey, lockValue);
        }
    }

    /**
     * 处理第三方支付回调
     */
    @Override
    public void handlePaymentCallback(Map<String, String> callbackParams) {
        // 1. 获取订单号
        String outTradeNo = callbackParams.get("out_trade_no");
        if (outTradeNo == null || outTradeNo.isEmpty()) {
            throw new RuntimeException("订单号不能为空");
        }

        // 2. 获取分布式锁
        String lockKey = LOCK_PREFIX + outTradeNo;
        String lockValue = UUID.randomUUID().toString();

        try {
            Boolean locked = redisTemplate.opsForValue().setIfAbsent(
                    lockKey,
                    lockValue,
                    LOCK_EXPIRE_SECONDS,
                    TimeUnit.SECONDS
            );

            if (Boolean.FALSE.equals(locked)) {
                log.warn("订单{}正在处理中，已拒绝重复回调", outTradeNo);
                return;
            }

            // 3. 处理回调
            processCallback(callbackParams);

        } finally {
            // 4. 释放锁
            releaseLock(lockKey, lockValue);
        }
    }

    /**
     * 执行支付回调的核心业务逻辑
     */
    private void processCallback(Map<String, String> callbackParams) {
        // 2. 获取订单号和交易状态
        String outTradeNo = callbackParams.get("out_trade_no");
        String tradeStatus = callbackParams.get("trade_status");

        // 3. 查询支付记录
        PaymentRecord paymentRecord = paymentMapper.selectByTransactionId(outTradeNo);
        if (paymentRecord == null) {
            throw new RuntimeException("支付记录不存在：" + outTradeNo);
        }

        // 4. 检查订单状态（避免重复处理）
        if (paymentRecord.getStatus() != PaymentStatus.PENDING.getCode()) {
            log.warn("订单{}已处理，状态：{}", outTradeNo, paymentRecord.getStatus());
            return;
        }

        // 5. 根据交易状态更新数据
        if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) { // 支付成功
            // 获取订单信息
            ShopOrder order = orderApi.getOrderInfo(paymentRecord.getOrderId());
            if (order != null) {
                // 更新订单和支付记录状态
                updateOrderAndPaymentStatus(order, paymentRecord, PaymentStatus.SUCCESS.getCode(), ShopOrderStatus.PAID.getCode());
            }

            log.info("订单{}支付成功", outTradeNo);
        } else { // 支付失败
            // 获取订单信息
            ShopOrder order = orderApi.getOrderInfo(paymentRecord.getOrderId());
            if (order != null) {
                // 更新订单和支付记录状态
                updateOrderAndPaymentStatus(order, paymentRecord, PaymentStatus.FAILED.getCode(), ShopOrderStatus.CANCELED.getCode());
            }

            log.info("订单{}支付失败，状态：{}", outTradeNo, tradeStatus);
        }
    }

    /**
     * 根据交易号处理支付结果（用于前端回调）
     */
    @Override
    public boolean processPaymentResult(String outTradeNo) {
        AlipayTradeQueryResponse response = payUtil.query(outTradeNo);

        if (response != null && response.isSuccess()) {
            // 检查交易状态
            String tradeStatus = response.getTradeStatus();
            // 获取支付记录
            PaymentRecord paymentRecord = paymentMapper.selectByTransactionId(outTradeNo);
            if (paymentRecord == null) {
                log.error("支付记录不存在：{}", outTradeNo);
                return false;
            }
            // 获取订单信息
            ShopOrder order = orderApi.getOrderInfo(paymentRecord.getOrderId());
            if (order == null) {
                log.error("订单不存在：{}", paymentRecord.getOrderId());
                return false;
            }

            // 根据交易状态处理
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                // 支付成功，更新订单和支付记录状态
                updateOrderAndPaymentStatus(order, paymentRecord, PaymentStatus.SUCCESS.getCode(), ShopOrderStatus.PAID.getCode());
                return true;
            } else if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
                // 等待支付，不更新状态
                log.info("订单{}等待支付", outTradeNo);
                return false;
            } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                // 交易已关闭
                updateOrderAndPaymentStatus(order, paymentRecord, PaymentStatus.FAILED.getCode(), ShopOrderStatus.CANCELED.getCode());
                return false;
            }
        }
        return false;
    }

    /**
     * 更新订单和支付记录状态
     */
    private void updateOrderAndPaymentStatus(ShopOrder order, PaymentRecord paymentRecord, Integer paymentStatus, Integer orderStatus) {
        // 获取分布式锁，防止并发更新
        String lockKey = LOCK_PREFIX + "update:" + order.getId();
        String lockValue = UUID.randomUUID().toString();

        try {
            Boolean locked = redisTemplate.opsForValue().setIfAbsent(
                    lockKey,
                    lockValue,
                    LOCK_EXPIRE_SECONDS,
                    TimeUnit.SECONDS
            );

            if (!locked) {
                log.warn("订单{}正在更新状态，稍后重试", order.getId());
                return;
            }

            // 检查订单状态，避免重复处理
            if (!order.getStatus().equals(ShopOrderStatus.PENDING.getCode())) {
                log.warn("订单{}状态已更新为{}，不再处理", order.getId(), order.getStatus());
                return;
            }

            // 更新支付记录状态
            paymentRecord.setStatus(paymentStatus);
            paymentRecord.setUpdateTime(new Date());
            paymentMapper.updateById(paymentRecord);

            // 更新订单状态
            order.setStatus(orderStatus);
            order.setUpdateTime(new Date());
            orderApi.updateOrderStatus(order.getId(), orderStatus);

            // 如果支付成功，发送支付成功消息
            if (PaymentStatus.SUCCESS.getCode()==paymentStatus) {
                sendPaymentSuccessMessage(order, paymentRecord);
            }

            log.info("订单{}状态更新为{}，支付记录状态更新为{}", order.getId(), orderStatus, paymentStatus);

        } finally {
            // 释放锁
            releaseLock(lockKey, lockValue);
        }
    }

    /**
     * 发送支付成功消息
     */
    private void sendPaymentSuccessMessage(ShopOrder order, PaymentRecord paymentRecord) {
        PaymentSuccessMessage message = new PaymentSuccessMessage();
        message.setOrderId(order.getId());
        message.setOrderNumber(order.getOrderNumber());
        message.setTransactionId(paymentRecord.getTransactionId());
        message.setPaymentTime(new Date());
        message.setAmount(paymentRecord.getAmount());
        message.setPaymentMethod(paymentRecord.getPaymentMethod());

        rabbitTemplate.convertAndSend(
                ORDER_PAY_SUCCESS_EXCHANGE,
                ORDER_PAY_SUCCESS_ROUTING_KEY,
                message
        );

        log.info("发送支付成功消息: {}", order.getOrderNumber());
    }

    /**
     * 释放分布式锁（使用Lua脚本保证原子性）
     */
    private void releaseLock(String lockKey, String lockValue) {
        // Lua脚本：如果锁的value等于传入的value，则删除锁，否则不操作
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] " +
                "then return redis.call('del', KEYS[1]) " +
                "else return 0 end";

        try {
            // 执行Lua脚本
            Long result = (Long) redisTemplate.execute(
                    new DefaultRedisScript<>(script, Long.class),
                    Collections.singletonList(lockKey),
                    lockValue
            );
            if (result == 1) {
                log.info("释放锁成功：{}", lockKey);
            } else {
                log.warn("释放锁失败（可能已过期或被其他线程释放）：{}", lockKey);
            }
        } catch (Exception e) {
            log.error("释放锁异常：{}", lockKey, e);
        }
    }

    /**
     * 生成交易ID
     */
    private String generateTransactionId() {
        return "PAY" + System.currentTimeMillis() + RandomStringUtils.randomNumeric(6);
    }

    /**
     * 查询支付记录
     */
    @Override
    public PaymentRecord getPaymentRecord(String transactionId) {
        return paymentMapper.selectByTransactionId(transactionId);
    }

    // 用户钱包退款
    @Override
    public void refund(String orderId) {
        ShopOrder order = orderApi.getOrderInfo(Integer.parseInt(orderId));
        PaymentRecord paymentRecord = paymentMapper.selectByTransactionId(orderId);

        if (paymentRecord == null) {
            throw new RuntimeException("支付记录不存在");
        }

        if (paymentRecord.getStatus() != PaymentStatus.SUCCESS.getCode()) {
            throw new RuntimeException("支付记录状态错误");
        }

        // 退款
        userApi.increaseBalance(Long.valueOf(order.getUserId()), paymentRecord.getAmount());

        // 给卖家扣钱
        userApi.deductBalance(Long.valueOf(order.getSellerId()), paymentRecord.getAmount());

        // 更新支付记录状态
        paymentRecord.setStatus(PaymentStatus.REFUNDED.getCode());
        paymentRecord.setUpdateTime(new Date());
        paymentMapper.updateById(paymentRecord);

        // 更新订单状态
        order.setStatus(ShopOrderStatus.REFUNDED.getCode());
        order.setUpdateTime(new Date());
        orderApi.updateOrderStatus(order.getId(), order.getStatus());
        // 商品重新上架
        contentApi.updateStatus(order.getItemId(), 1);
        log.info("订单{}退款成功", orderId);
    }

    @Override
    public void updateOrderStatus(String orderId, Integer status) {
        ShopOrder order = new ShopOrder();
        order.setId(Integer.parseInt(orderId));
        order.setStatus(status);
        order.setUpdateTime(new Date());
        orderApi.updateOrderStatus(order.getId(), status);
        log.info("订单{}状态更新成功：{}", orderId, status);
    }
}